package com.ymk.mq;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.rabbitmq.client.Channel;
import com.ymk.base.cmd.CmdSign;
import com.ymk.base.cmd.SchedulerCmd;
import com.ymk.base.exception.MallException;
import com.ymk.core.code.resp.RespCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

@Component
public class MessageReceiver {
    private final static Logger logger = LoggerFactory.getLogger(MessageReceiver.class);

    /**
     * 订单消息
     *
     * @param message 消息
     * @throws Exception e
     */
    @RabbitListener(queues = RabbitmqCode.ORDER_QUEUE)
    @RabbitHandler
    public void orderReceiver(Message message,
                              Channel channel,
                              @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception {
        String body = new String(message.getBody(), StandardCharsets.UTF_8);
        CmdSign cmdSign = JSONObject.parseObject(body, CmdSign.class);
        this.execute(cmdSign, channel, tag, RabbitmqCode.ORDER_QUEUE);
    }

    /**
     * 商品消息
     *
     * @param message 消息
     * @throws Exception e
     */
    @RabbitListener(queues = RabbitmqCode.GOODS_QUEUE)
    @RabbitHandler
    public void goodsReceiver(Message message,
                              Channel channel,
                              @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception {
        String body = new String(message.getBody(), StandardCharsets.UTF_8);
        CmdSign cmdSign = JSONObject.parseObject(body, CmdSign.class);
        this.execute(cmdSign, channel, tag, RabbitmqCode.GOODS_QUEUE);
    }

    /**
     * 会员消息
     *
     * @param message 消息
     * @throws Exception e
     */
    @RabbitListener(queues = RabbitmqCode.MEMBER_QUEUE)
    @RabbitHandler
    public void memberReceiver(Message message,
                               Channel channel,
                               @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception {
        String body = new String(message.getBody(), StandardCharsets.UTF_8);
        CmdSign cmdSign = JSONObject.parseObject(body, CmdSign.class);
        this.execute(cmdSign, channel, tag, RabbitmqCode.MEMBER_QUEUE);
    }

    /**
     * 通知消息
     *
     * @param message 消息
     * @throws Exception e
     */
    @RabbitListener(queues = RabbitmqCode.NOTICE_QUEUE)
    @RabbitHandler
    public void noticeReceiver(Message message,
                               Channel channel,
                               @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception {
        String body = new String(message.getBody(), StandardCharsets.UTF_8);
        CmdSign cmdSign = JSONObject.parseObject(body, CmdSign.class);
        this.execute(cmdSign, channel, tag, RabbitmqCode.NOTICE_QUEUE);
    }



    /**
     * STAT 统计指令
     *
     * @param message 消息
     * @throws Exception e
     */
    @RabbitListener(queues = RabbitmqCode.STAT_QUEUE)
    @RabbitHandler
    public void statReceiver(Message message,
                             Channel channel,
                             @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception {
        String body = new String(message.getBody(), StandardCharsets.UTF_8);
        CmdSign cmdSign = JSONObject.parseObject(body, CmdSign.class);
        this.execute(cmdSign, channel, tag, RabbitmqCode.STAT_QUEUE);
    }

    /**
     * MKT 推广指令
     *
     * @param message 消息
     * @throws Exception e
     */
    @RabbitListener(queues = RabbitmqCode.MKT_QUEUE)
    @RabbitHandler
    public void mktReceiver(Message message,
                            Channel channel,
                            @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception {
        String body = new String(message.getBody(), StandardCharsets.UTF_8);
        CmdSign cmdSign = JSONObject.parseObject(body, CmdSign.class);
        this.execute(cmdSign, channel, tag, RabbitmqCode.MKT_QUEUE);
    }


    /**
     * 支付指令
     *
     * @param message 消息
     * @throws Exception e
     */
    @RabbitListener(queues = RabbitmqCode.PAY_QUEUE)
    @RabbitHandler
    public void payReceiver(Message message,
                            Channel channel,
                            @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception {
        String body = new String(message.getBody(), StandardCharsets.UTF_8);
        CmdSign cmdSign = JSONObject.parseObject(body, CmdSign.class);
        this.execute(cmdSign, channel, tag, RabbitmqCode.PAY_QUEUE);
    }


    protected CmdSign execute(CmdSign cmdSign, Channel channel, long tag, String queue) {
        CmdSign respSign = null;
        try {
            respSign = this.scheduler.schedule(null, cmdSign);
            channel.basicAck(tag, false);
        } catch (MallException e) {
            respSign = new CmdSign(cmdSign);
            respSign.setRespCode(RespCode.CODE_ERROR);
            respSign.setMsg(e.getMessage());
            logger.info(e.getMsg());
            try {
                channel.basicAck(tag, false);
            } catch (IOException e2) {
                e2.printStackTrace();
            }
        } catch (Exception e) {
            logger.error(new Gson().toJson(cmdSign));
            logger.error(e.getMessage(), e);
            respSign = new CmdSign(cmdSign);
            respSign.setRespCode(RespCode.CODE_ERROR);

            try {
                channel.basicAck(tag, false);
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return respSign;
    }

    @Autowired
    private SchedulerCmd scheduler;
    @Autowired
    private MessageSender messageSender;

}
